From 4d5616b775a152f2cb13be98d811a80314cdf61b Mon Sep 17 00:00:00 2001 From: Hollis Blanchard Date: Fri, 13 Jul 2007 17:28:15 -0500 Subject: [PATCH] [POWERPC][XEN] Enable in-guest performance monitoring. - Lazily save and restore the performance monitor counters when switching domains. - Control with the H_PERFMON PAPR hypercall. - Ignore guest perfmon exceptions that land in Xen. Signed-off-by: Christian Ehrhardt Signed-off-by: Hollis Blanchard --- xen/arch/powerpc/exceptions.h | 3 +- xen/arch/powerpc/of_handler/papr.S | 2 +- xen/arch/powerpc/papr/Makefile | 1 + xen/arch/powerpc/papr/h_perfmon.c | 158 ++++++++++++++++++++++++ xen/arch/powerpc/powerpc64/domain.c | 46 ++++++- xen/arch/powerpc/powerpc64/exceptions.S | 25 +++- xen/include/asm-powerpc/domain.h | 21 +++- xen/include/asm-powerpc/papr.h | 1 + xen/include/asm-powerpc/processor.h | 138 ++++++++++++++++++++- xen/include/asm-powerpc/reg_defs.h | 27 +++- xen/include/asm-powerpc/xenoprof.h | 76 +++++++++++- 11 files changed, 490 insertions(+), 8 deletions(-) create mode 100644 xen/arch/powerpc/papr/h_perfmon.c diff --git a/xen/arch/powerpc/exceptions.h b/xen/arch/powerpc/exceptions.h index 7a71faee8d..2b294ce94e 100644 --- a/xen/arch/powerpc/exceptions.h +++ b/xen/arch/powerpc/exceptions.h @@ -13,7 +13,7 @@ * along with this program; if not, write to the Free Software * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * Copyright (C) IBM Corp. 2005 + * Copyright IBM Corp. 2005, 2007 * * Authors: Hollis Blanchard */ @@ -39,6 +39,7 @@ extern multiboot_info_t *boot_of_init(ulong r3, ulong r4, ulong vec, ulong r6, extern void do_timer(struct cpu_user_regs *regs); extern void do_dec(struct cpu_user_regs *regs); +extern void do_perfmon(struct cpu_user_regs *regs); extern void program_exception( struct cpu_user_regs *regs, unsigned long cookie); diff --git a/xen/arch/powerpc/of_handler/papr.S b/xen/arch/powerpc/of_handler/papr.S index 16ba6cfed4..9f979f0da3 100644 --- a/xen/arch/powerpc/of_handler/papr.S +++ b/xen/arch/powerpc/of_handler/papr.S @@ -67,7 +67,7 @@ PAPR(5, 1,papr_real_to_logical, H_REAL_TO_LOGICAL) PAPR(5, 1,papr_pci_config_read, H_PCI_CONFIG_READ) PAPR(5, 0,papr_pci_config_write, H_PCI_CONFIG_WRITE) - PAPR(5, 1,papr_grant_logical, H_GRANT_LOGICAL) +PAPR(5, 1,papr_grant_logical, H_GRANT_LOGICAL) PAPR(1, 1,papr_accept_logical, H_ACCEPT_LOGICAL) PAPR(0, 2,papr_rescind_logical, H_RESCIND_LOGICAL) PAPR(3, 0,papr_register_vterm, H_REGISTER_VTERM) diff --git a/xen/arch/powerpc/papr/Makefile b/xen/arch/powerpc/papr/Makefile index 8ea5183d3f..f1ba02c6ac 100644 --- a/xen/arch/powerpc/papr/Makefile +++ b/xen/arch/powerpc/papr/Makefile @@ -8,3 +8,4 @@ obj-y += tce.o obj-y += vtce.o obj-$(papr_vterm) += vterm.o obj-y += xlate.o +obj-y += h_perfmon.o diff --git a/xen/arch/powerpc/papr/h_perfmon.c b/xen/arch/powerpc/papr/h_perfmon.c new file mode 100644 index 0000000000..33de44f36f --- /dev/null +++ b/xen/arch/powerpc/papr/h_perfmon.c @@ -0,0 +1,158 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright IBM Corp. 2007 + * + * Authors: Christian Ehrhardt + */ +#undef DEBUG + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define H_PERFMON_ENABLE (1UL << 63) +#define H_PERFMON_THRESHOLDGRANULARITY (1UL << 62) + +#ifdef DEBUG +#define DBG(fmt...) printk(fmt) +#else +#define DBG(fmt...) +#endif + +/* FIXME workaround - these are just the default values, need the values set to + * linux via sysfs up-to-date. */ +int pmc_reset_val[NUM_PMCS] = { (0x8000000-0x0), + (0x8000000-0x100000), + (0x8000000-0x0), + (0x8000000-0x0), + (0x8000000-0x0), + (0x8000000-0x0), + (0x8000000-0x0), + (0x8000000-0x0)}; +int perf_count_active_vcpu; +perf_sprs_t perf_clear_sprs; +static DEFINE_SPINLOCK(perf_pmu_lock); + +static inline int has_pmu(void) { return 1; } + +void do_perfmon(struct cpu_user_regs *regs) +{ + ulong mmcra = mfmmcra(); + ulong mmcr0 = mfmmcr0(); + int pmc,i; + + if ((mmcra & MMCRA_SAMPHV) && !(mmcra & MMCRA_SAMPPR)) { + /* TODO Hypervisor sample - support to sample xen, + * pass the sample to the primary sampling domain via an event channel. + */ + printk("do_perfmon - called with sample of xen space\n"); + print_perf_status(); + BUG(); + } + + /* Dom sample postponed into xen space + * Currently just ignored (decreases accuracy) + * TODO pass the Dom samples to the appropriate domain via an event channel + * TODO get access to the real pmc_reset_val currently used by the domain + * to reset counter safe and valid + */ + + for (i = 0; i < NUM_PMCS; ++i) { + pmc = ctr_read(i); + if (pmc < 0) { + DBG("postponed perfmon exception - PMC%d < 0 - reset to default " + "'0x%0x'\n", i, pmc_reset_val[i]); + ctr_write(i,pmc_reset_val[i]); + } + } + + mmcr0 |= MMCR0_PMAE; + mmcr0 &= ~MMCR0_FC; + mtmmcr0(mmcr0); +} + +static void h_perfmon(struct cpu_user_regs *regs) +{ + ulong mode_set = regs->gprs[4]; + ulong mode_reset = regs->gprs[5]; + struct vcpu *v = get_current(); + struct domain *d = v->domain; + + if (!has_pmu()) { + regs->gprs[3] = H_Function; + return; + } + + /* only bits 0&1 are supported by H_PERFMON */ + if (((mode_set | mode_reset) & ~(H_PERFMON_ENABLE | + H_PERFMON_THRESHOLDGRANULARITY)) != 0) { + regs->gprs[3] = H_Parameter; + return; + } + /* enable or disable it, not both */ + if ((mode_set & mode_reset) != 0) { + regs->gprs[3] = H_Resource; + return; + } + + spin_lock(&perf_pmu_lock); + if (mode_set & H_PERFMON_ENABLE) { + if (v->arch.pmu_enabled) { + DBG("H_PERFMON call on already enabled PMU for domain '%d' on " + "vcpu '%d'\n", d->domain_id, v->vcpu_id); + goto success; + } + + if (!perf_count_active_vcpu) { + save_pmc_sprs(&perf_clear_sprs); +#ifdef DEBUG + DBG("H_PERFMON Saved initial clear performance special purpose " + "registers\n"); + print_perf_status(); +#endif + } + v->arch.pmu_enabled = 1; + perf_count_active_vcpu++; + printk("H_PERFMON call enabled PMU for domain '%d' on vcpu '%d'\n", + d->domain_id, v->vcpu_id); + } else if (mode_reset & H_PERFMON_ENABLE) { + if (!v->arch.pmu_enabled) { + DBG("H_PERFMON call on already disabled PMU for domain '%d' on " + "vcpu '%d'\n", d->domain_id, v->vcpu_id); + goto success; + } + v->arch.pmu_enabled = 0; + perf_count_active_vcpu--; + printk("H_PERFMON call disabled PMU for domain '%d' on vcpu '%d'\n", + d->domain_id, v->vcpu_id); + } else { + regs->gprs[3] = H_Parameter; + } + +success: + regs->gprs[3] = H_Success; + spin_unlock(&perf_pmu_lock); +} + +__init_papr_hcall(H_PERFMON, h_perfmon); diff --git a/xen/arch/powerpc/powerpc64/domain.c b/xen/arch/powerpc/powerpc64/domain.c index f9633ccfbd..acf5969c7a 100644 --- a/xen/arch/powerpc/powerpc64/domain.c +++ b/xen/arch/powerpc/powerpc64/domain.c @@ -13,17 +13,49 @@ * along with this program; if not, write to the Free Software * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * Copyright (C) IBM Corp. 2005 + * Copyright IBM Corp. 2005, 2007 * * Authors: Jimi Xenidis + * Christian Ehrhardt */ #include #include #include #include +#include #include +void save_pmc_sprs(perf_sprs_t *p_sprs) +{ + p_sprs->mmcr0 = mfmmcr0(); + p_sprs->mmcr1 = mfmmcr1(); + p_sprs->mmcra = mfmmcra(); + p_sprs->pmc[0] = mfpmc1(); + p_sprs->pmc[1] = mfpmc2(); + p_sprs->pmc[2] = mfpmc3(); + p_sprs->pmc[3] = mfpmc4(); + p_sprs->pmc[4] = mfpmc5(); + p_sprs->pmc[5] = mfpmc6(); + p_sprs->pmc[6] = mfpmc7(); + p_sprs->pmc[7] = mfpmc8(); +} + +void load_pmc_sprs(perf_sprs_t *p_sprs) +{ + mtpmc1(p_sprs->pmc[0]); + mtpmc2(p_sprs->pmc[1]); + mtpmc3(p_sprs->pmc[2]); + mtpmc4(p_sprs->pmc[3]); + mtpmc5(p_sprs->pmc[4]); + mtpmc6(p_sprs->pmc[5]); + mtpmc7(p_sprs->pmc[6]); + mtpmc8(p_sprs->pmc[7]); + mtmmcra(p_sprs->mmcra); + mtmmcr1(p_sprs->mmcr1); + mtmmcr0(p_sprs->mmcr0); +} + void save_sprs(struct vcpu *v) { v->arch.timebase = mftb(); @@ -36,6 +68,11 @@ void save_sprs(struct vcpu *v) v->arch.dar = mfdar(); v->arch.dsisr = mfdsisr(); + if (v->arch.pmu_enabled) { + save_pmc_sprs(&(v->arch.perf_sprs)); + v->arch.perf_sprs_stored = 1; + } + save_cpu_sprs(v); } @@ -50,6 +87,13 @@ void load_sprs(struct vcpu *v) mtdar(v->arch.dar); mtdsisr(v->arch.dsisr); + if (v->arch.pmu_enabled) { + if (v->arch.perf_sprs_stored) + load_pmc_sprs(&(v->arch.perf_sprs)); + else + load_pmc_sprs(&perf_clear_sprs); + } + load_cpu_sprs(v); /* adjust the DEC value to account for cycles while not diff --git a/xen/arch/powerpc/powerpc64/exceptions.S b/xen/arch/powerpc/powerpc64/exceptions.S index 07e7217b6d..9eec6d9d10 100644 --- a/xen/arch/powerpc/powerpc64/exceptions.S +++ b/xen/arch/powerpc/powerpc64/exceptions.S @@ -105,6 +105,12 @@ LOAD_GPRS "(\from+1)", \to, \uregs nop .endm +.macro PMU_SAVE_STATE scratch + mfspr \scratch,SPRN_MMCR0 /* ensure MMCR0[FCH] is 1 */ + ori \scratch,\scratch,MMCR0_FCH + mtspr SPRN_MMCR0, \scratch +.endm + .macro EXCEPTION_HEAD parea continue /* make room for cpu_user_regs */ subi r1, r1, STACK_VOLATILE_AREA + UREGS_sizeof @@ -156,7 +162,7 @@ LOAD_GPRS "(\from+1)", \to, \uregs ori r0, r0, MSR_RI@l mtmsrd r0 - + PMU_SAVE_STATE r0 .endm /* For exceptions that use HSRR0/1 (preserving the OS's SRR0/1). */ @@ -183,6 +189,7 @@ LOAD_GPRS "(\from+1)", \to, \uregs ori r0, r0, MSR_RI@l mtmsrd r0 + PMU_SAVE_STATE r0 .endm /* Hypervisor exception handling code; copied to physical address zero. */ @@ -328,6 +335,12 @@ ex_fp: li r0, 0xe00 /* exception vector for GDB stub */ bctr + . = 0xf00 +ex_perfmon: + GET_STACK r13 SPRN_SRR1 + EXCEPTION_HEAD r13 ex_perfmon_continued + bctr + .align 3 .globl exception_vectors_end @@ -452,6 +465,16 @@ ex_dec_continued: addi r1, r1, STACK_FRAME_OVERHEAD /* restore stack to cpu_user_regs */ b fast_resume +ex_perfmon_continued: + EXCEPTION_SAVE_STATE r1 + LOADADDR r12, do_perfmon + mr r3, r1 /* pass pointer to cpu_user_regs */ + subi r1, r1, STACK_FRAME_OVERHEAD /* make a "caller" stack frame */ + CALL_CFUNC r12 + + addi r1, r1, STACK_FRAME_OVERHEAD /* restore stack to cpu_user_regs */ + b fast_resume + ex_hdec_continued: /* When we get an HDEC, we (almost?) always context_switch, so we need to * save the nonvolatiles. */ diff --git a/xen/include/asm-powerpc/domain.h b/xen/include/asm-powerpc/domain.h index 58a1417de9..957667ddec 100644 --- a/xen/include/asm-powerpc/domain.h +++ b/xen/include/asm-powerpc/domain.h @@ -16,6 +16,7 @@ * Copyright IBM Corp. 2005, 2007 * * Authors: Hollis Blanchard + * Christian Ehrhardt */ #ifndef _ASM_DOMAIN_H_ @@ -30,6 +31,17 @@ #include #include + +typedef struct { + ulong mmcr0; + ulong mmcr1; + ulong mmcra; + ulong pmc[NUM_PMCS]; +} perf_sprs_t; + +extern atomic_t perf_count_active; +extern perf_sprs_t perf_clear_sprs; + struct arch_domain { struct domain_htab htab; @@ -84,7 +96,12 @@ struct arch_vcpu { ulong timebase; ulong dar; ulong dsisr; - + + /* performance monitor sprs per vcpu */ + int pmu_enabled; + int perf_sprs_stored; + perf_sprs_t perf_sprs; + /* Segment Lookaside Buffer */ struct slb_entry slb_entries[NUM_SLB_ENTRIES]; @@ -102,6 +119,8 @@ extern void full_resume(void); extern void save_sprs(struct vcpu *); extern void load_sprs(struct vcpu *); +extern void save_pmc_sprs(perf_sprs_t *p_sprs); +extern void load_pmc_sprs(perf_sprs_t *p_sprs); extern void save_segments(struct vcpu *); extern void load_segments(struct vcpu *); extern void save_float(struct vcpu *); diff --git a/xen/include/asm-powerpc/papr.h b/xen/include/asm-powerpc/papr.h index 03679ca2fa..a04477ed1e 100644 --- a/xen/include/asm-powerpc/papr.h +++ b/xen/include/asm-powerpc/papr.h @@ -66,6 +66,7 @@ #define H_IPOLL 0x0070 /* Crit Yes int */ #define H_XIRR 0x0074 /* Crit Yes int */ #define H_MIGRATE_PCI_TCE 0x0078 /* Norm Yes-if LRDR migrate */ +#define H_PERFMON 0x007c /* Norm Yes-if PMU perfmon */ #define H_CEDE 0x00e0 /* Crit Yes splpar */ #define H_CONFER 0x00e4 #define H_PROD 0x00e8 diff --git a/xen/include/asm-powerpc/processor.h b/xen/include/asm-powerpc/processor.h index fe43304e82..152ba504ac 100644 --- a/xen/include/asm-powerpc/processor.h +++ b/xen/include/asm-powerpc/processor.h @@ -13,9 +13,10 @@ * along with this program; if not, write to the Free Software * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * Copyright (C) IBM Corp. 2005, 2006 + * Copyright IBM Corp. 2005, 2006, 2007 * * Authors: Hollis Blanchard + * Christian Ehrhardt */ #ifndef _ASM_PROCESSOR_H_ @@ -200,6 +201,141 @@ static inline ulong mfr1(void) return r1; } +static inline void mtmmcr0(ulong val) +{ + asm volatile ("mtspr %0, %1" : : "i"(SPRN_MMCR0), "r"(val)); +} +static inline ulong mfmmcr0(void) +{ + ulong rval; + asm volatile ("mfspr %0, %1" : "=r"(rval) : "i"(SPRN_MMCR0)); + return rval; +} + +static inline void mtmmcr1(ulong val) +{ + asm volatile ("mtspr %0, %1" : : "i"(SPRN_MMCR1), "r"(val)); +} +static inline ulong mfmmcr1(void) +{ + ulong rval; + asm volatile ("mfspr %0, %1" : "=r"(rval) : "i"(SPRN_MMCR1)); + return rval; +} + +static inline void mtmmcra(ulong val) +{ + asm volatile ("mtspr %0, %1" : : "i"(SPRN_MMCRA), "r"(val)); +} +static inline ulong mfmmcra(void) +{ + ulong rval; + asm volatile ("mfspr %0, %1" : "=r"(rval) : "i"(SPRN_MMCRA)); + return rval; +} + +static inline void mtpmc1(ulong val) +{ + asm volatile ("mtspr %0, %1" : : "i"(SPRN_PMC1), "r"(val)); +} +static inline ulong mfpmc1(void) +{ + ulong rval; + asm volatile ("mfspr %0, %1" : "=r"(rval) : "i"(SPRN_PMC1)); + return rval; +} + +static inline void mtpmc2(ulong val) +{ + asm volatile ("mtspr %0, %1" : : "i"(SPRN_PMC2), "r"(val)); +} +static inline ulong mfpmc2(void) +{ + ulong rval; + asm volatile ("mfspr %0, %1" : "=r"(rval) : "i"(SPRN_PMC2)); + return rval; +} + +static inline void mtpmc3(ulong val) +{ + asm volatile ("mtspr %0, %1" : : "i"(SPRN_PMC3), "r"(val)); +} +static inline ulong mfpmc3(void) +{ + ulong rval; + asm volatile ("mfspr %0, %1" : "=r"(rval) : "i"(SPRN_PMC3)); + return rval; +} + +static inline void mtpmc4(ulong val) +{ + asm volatile ("mtspr %0, %1" : : "i"(SPRN_PMC4), "r"(val)); +} +static inline ulong mfpmc4(void) +{ + ulong rval; + asm volatile ("mfspr %0, %1" : "=r"(rval) : "i"(SPRN_PMC4)); + return rval; +} + +static inline void mtpmc5(ulong val) +{ + asm volatile ("mtspr %0, %1" : : "i"(SPRN_PMC5), "r"(val)); +} +static inline ulong mfpmc5(void) +{ + ulong rval; + asm volatile ("mfspr %0, %1" : "=r"(rval) : "i"(SPRN_PMC5)); + return rval; +} + +static inline void mtpmc6(ulong val) +{ + asm volatile ("mtspr %0, %1" : : "i"(SPRN_PMC6), "r"(val)); +} +static inline ulong mfpmc6(void) +{ + ulong rval; + asm volatile ("mfspr %0, %1" : "=r"(rval) : "i"(SPRN_PMC6)); + return rval; +} + +static inline void mtpmc7(ulong val) +{ + asm volatile ("mtspr %0, %1" : : "i"(SPRN_PMC7), "r"(val)); +} +static inline ulong mfpmc7(void) +{ + ulong rval; + asm volatile ("mfspr %0, %1" : "=r"(rval) : "i"(SPRN_PMC7)); + return rval; +} + +static inline void mtpmc8(ulong val) +{ + asm volatile ("mtspr %0, %1" : : "i"(SPRN_PMC8), "r"(val)); +} +static inline ulong mfpmc8(void) +{ + ulong rval; + asm volatile ("mfspr %0, %1" : "=r"(rval) : "i"(SPRN_PMC8)); + return rval; +} + +static inline ulong mfsdar(void) +{ + ulong rval; + asm volatile ("mfspr %0, %1" : "=r"(rval) : "i"(SPRN_SDAR)); + return rval; +} + +static inline ulong mfsiar(void) +{ + ulong rval; + asm volatile ("mfspr %0, %1" : "=r"(rval) : "i"(SPRN_SIAR)); + return rval; +} + static inline void mtsprg0(ulong val) { __asm__ __volatile__ ("mtspr %0, %1" : : "i"(SPRN_SPRG0), "r"(val)); diff --git a/xen/include/asm-powerpc/reg_defs.h b/xen/include/asm-powerpc/reg_defs.h index 99a3ba2f5c..f72e1591c4 100644 --- a/xen/include/asm-powerpc/reg_defs.h +++ b/xen/include/asm-powerpc/reg_defs.h @@ -13,9 +13,10 @@ * along with this program; if not, write to the Free Software * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * Copyright (C) IBM Corp. 2005 + * Copyright IBM Corp. 2005, 2007 * * Authors: Jimi Xenidis + * Christian Ehrhardt */ #ifndef _ASM_REG_DEFS_H_ @@ -166,8 +167,32 @@ #define SPRN_LPCR 318 #define SPRN_LPIDR 319 +/* Performance monitor spr encodings */ +#define SPRN_MMCRA 786 +#define MMCRA_SAMPHV UL(0x10000000) /* state of MSR HV when SIAR set */ +#define MMCRA_SAMPPR UL(0x08000000) /* state of MSR PR when SIAR set */ +#define MMCRA_SAMPLE_ENABLE UL(0x00000001) /* enable sampling */ +#define NUM_PMCS 8 +#define SPRN_PMC1 787 +#define SPRN_PMC2 788 +#define SPRN_PMC3 789 +#define SPRN_PMC4 790 +#define SPRN_PMC5 791 +#define SPRN_PMC6 792 +#define SPRN_PMC7 793 +#define SPRN_PMC8 794 +#define SPRN_MMCR0 795 +#define MMCR0_FC UL(0x80000000) /* freeze counters */ +#define MMCR0_FCS UL(0x40000000) /* freeze in supervisor state */ +#define MMCR0_FCP UL(0x20000000) /* freeze in problem state */ +#define MMCR0_FCM1 UL(0x10000000) /* freeze counters while MSR mark = 1 */ +#define MMCR0_FCM0 UL(0x08000000) /* freeze counters while MSR mark = 0 */ +#define MMCR0_PMAE UL(0x04000000) /* performance monitor alert enabled */ +#define MMCR0_PMAO UL(0x00000080) /* performance monitor alert occurred */ +#define MMCR0_FCH UL(0x00000001) /* freeze conditions in hypervisor */ #define SPRN_SIAR 796 #define SPRN_SDAR 797 +#define SPRN_MMCR1 798 /* As defined for PU G4 */ #define SPRN_HID0 1008 diff --git a/xen/include/asm-powerpc/xenoprof.h b/xen/include/asm-powerpc/xenoprof.h index f9f52397dd..3d17cc5193 100644 --- a/xen/include/asm-powerpc/xenoprof.h +++ b/xen/include/asm-powerpc/xenoprof.h @@ -21,6 +21,80 @@ #ifndef __ASM_PPC_XENOPROF_H__ #define __ASM_PPC_XENOPROF_H__ -/* unimplemented */ +#include +#include +#include +#include + +/* All the classic PPC parts use these */ +static inline unsigned int ctr_read(unsigned int i) +{ + switch(i) { + case 0: + return mfpmc1(); + case 1: + return mfpmc2(); + case 2: + return mfpmc3(); + case 3: + return mfpmc4(); + case 4: + return mfpmc5(); + case 5: + return mfpmc6(); + case 6: + return mfpmc7(); + case 7: + return mfpmc8(); + default: + return 0; + } +} + +static inline void ctr_write(unsigned int i, unsigned int val) +{ + switch(i) { + case 0: + mtpmc1(val); + break; + case 1: + mtpmc2(val); + break; + case 2: + mtpmc3(val); + break; + case 3: + mtpmc4(val); + break; + case 4: + mtpmc5(val); + break; + case 5: + mtpmc6(val); + break; + case 6: + mtpmc7(val); + break; + case 7: + mtpmc8(val); + break; + default: + break; + } +} + +static inline void print_perf_status() +{ + ulong mmcr0 = mfmmcr0(); + ulong mmcr1 = mfmmcr1(); + ulong mmcra = mfmmcra(); + ulong sdar = mfsdar(); + ulong siar = mfsiar(); + printk("MMCR0 0x%0lX\n",mmcr0); + printk("MMCR1 0x%0lX\n",mmcr1); + printk("MMCRA 0x%0lX\n",mmcra); + printk("SIAR 0x%0lX\n",siar); + printk("SDAR 0x%0lX\n",sdar); +} #endif -- 2.30.2